home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / addr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  9.1 KB  |  458 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: addr.c,v 5.3 1992/11/10 08:18:25 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <syslog.h>
  13. #include <netdb.h>
  14.  
  15. #include "fsma.h"
  16. #include "pset.h"
  17.  
  18. #include "defs.h"
  19. #include "addr.h"
  20.  
  21. unsigned long inet_addr() ;
  22.  
  23. void msg() ;
  24. void parsemsg() ;
  25. void out_of_memory() ;
  26.  
  27. #define OPEN_CURLY_BRACKET            '{'
  28. #define CLOSED_CURLY_BRACKET        '}'
  29. #define COMMA                            ','
  30. #define DOT                                '.'
  31.  
  32. typedef enum { NUMERIC_ADDR, NET_ADDR, HOST_ADDR } address_e ;
  33.  
  34. typedef enum { CANT_PARSE, PARSED, ERROR } result_e ;
  35.  
  36. struct comp_addr
  37. {
  38.     address_e addr_type ;
  39.     unsigned long addr ;
  40.     unsigned long mask ;
  41. } ;
  42.  
  43. #define CAP( p )        ( (struct comp_addr *) (p) )
  44.  
  45.  
  46. static fsma_h comp_addr_allocator ;
  47.  
  48.  
  49. status_e addrlist_init()
  50. {
  51.     int flags = FSM_RETURN_ERROR ;
  52.  
  53. #ifdef DEBUG
  54.     flags |= FSM_ZERO_FREE ;
  55. #endif
  56.     comp_addr_allocator = fsm_create( sizeof( struct comp_addr ), 0, flags ) ;
  57.     return( ( comp_addr_allocator == NULL ) ? FAILED : OK ) ;
  58. }
  59.  
  60.  
  61. bool_int addrlist_match( addr_list, addr, matchp )
  62.     pset_h addr_list ;
  63.     struct in_addr *addr ;
  64.     unsigned long *matchp ;
  65. {
  66.     register unsigned long remote_addr = ntohl( addr->s_addr ) ;
  67.     register unsigned u ;
  68.  
  69.     for ( u = 0 ; u < pset_count( addr_list ) ; u++ )
  70.     {
  71.         register struct comp_addr *cap = CAP( pset_pointer( addr_list, u ) ) ;
  72.  
  73.         if ( ( remote_addr & cap->mask ) == cap->addr )
  74.         {
  75.             *matchp = cap->mask ;
  76.             return( TRUE ) ;
  77.         }
  78.     }
  79.     return( FALSE ) ;
  80. }
  81.  
  82.  
  83.  
  84. void addrlist_dump( addr_list, fd )
  85.     pset_h addr_list ;
  86.     int fd ;
  87. {
  88.     register unsigned u ;
  89.     struct in_addr inaddr ;
  90.     char *inet_ntoa() ;
  91.  
  92.     for ( u = 0 ; u < pset_count( addr_list ) ; u++ )
  93.     {
  94.         struct comp_addr *cap = CAP( pset_pointer( addr_list, u ) ) ;
  95.         char *type ;
  96.  
  97.         inaddr.s_addr = htonl( cap->addr ) ;
  98.         if ( cap->addr_type == NUMERIC_ADDR )
  99.             type = "NUMERIC" ;
  100.         else if ( cap->addr_type == NET_ADDR )
  101.             type = "NET" ;
  102.         else if ( cap->addr_type == HOST_ADDR )
  103.             type = "HOST" ;
  104.         else
  105.             type = "BAD" ;
  106.         
  107.         Sprint( fd, " %s(%s)", inet_ntoa( inaddr ), type ) ;
  108.     }
  109. }
  110.  
  111.  
  112. void addrlist_free( addr_list )
  113.     pset_h addr_list ;
  114. {
  115.     void free_pset() ;
  116.  
  117.     free_pset( addr_list, comp_addr_allocator ) ;
  118. }
  119.  
  120.  
  121.  
  122. PRIVATE status_e add( addr_list, cap )
  123.     pset_h addr_list ;
  124.     struct comp_addr *cap ;
  125. {
  126.     struct comp_addr *new_cap ;
  127.     char *func = "add" ;
  128.  
  129.     new_cap = CAP( fsm_alloc( comp_addr_allocator ) ) ;
  130.     if ( new_cap == NULL )
  131.     {
  132.         out_of_memory( func ) ;
  133.         return( FAILED ) ;
  134.     }
  135.  
  136.     *new_cap = *cap ;
  137.     if ( pset_add( addr_list, new_cap ) == NULL )
  138.     {
  139.         out_of_memory( func ) ;
  140.         fsm_free( comp_addr_allocator, (char *) new_cap ) ;
  141.         return( FAILED ) ;
  142.     }
  143.     return( OK ) ;
  144. }
  145.  
  146.  
  147. /*
  148.  * Find the address and remove it from the list
  149.  * Since there is no check when we add entries that an
  150.  * address is not entered twice, in this function we remove all
  151.  * addresses that match.
  152.  *
  153.  * XXX: we need to work on the way two cap's are considered equal
  154.  */
  155. PRIVATE status_e remove( addr_list, cap )
  156.     pset_h addr_list ;
  157.     struct comp_addr *cap ;
  158. {
  159.     register unsigned u = 0 ;
  160.     struct comp_addr *old_cap ;
  161.  
  162.     while ( u < pset_count( addr_list ) )
  163.     {
  164.         old_cap = CAP( pset_pointer( addr_list, u ) ) ;
  165.         if ( old_cap->addr == cap->addr && old_cap->mask == cap->mask )
  166.         {
  167.             pset_remove_index( addr_list, u ) ;
  168.             fsm_free( comp_addr_allocator, (char *) old_cap ) ;
  169.         }
  170.         else
  171.             u++ ;
  172.     }
  173.     return( OK ) ;
  174. }
  175.  
  176.  
  177. PRIVATE result_e net_addr( str_addr, op, addr_list )
  178.     char *str_addr ;
  179.     status_e (*op)() ;
  180.     pset_h addr_list ;
  181. {
  182.     /*
  183.      *
  184.      *  The following table demonstrates how the mask is determined
  185.      *  given a net number N and following the relation:
  186.      *     net #1 <= N <= #2
  187.      *
  188.      *     net #1      net #2      mask
  189.      *        0           0        FFFFFFFF    (this should be rejected)
  190.      *        1           FF       FF000000
  191.      *        100         FFFF     FFFF0000
  192.      *        10000       FFFFFF   FFFFFF00
  193.      *        1000000     FFFFFFFF FFFFFFFF
  194.      */
  195.     static struct { int lim, mask, shift } net_to_mask[] =
  196.     {
  197.         { 0,                 0xFF000000,    24    },
  198.         { 0xFF,            0xFFFF0000,    16    },
  199.         { 0xFFFF,        0xFFFFFF00,    8    },
  200.         { 0xFFFFFF,        0xFFFFFFFF,    0    },
  201.         { 0xFFFFFFFF,    0,                0    }
  202.     } ;
  203.     struct comp_addr ca ;
  204.     struct netent *nep ;
  205.     register unsigned long net_num ;
  206.     int i ;
  207.     char *func = "net_addr" ;
  208.  
  209.     nep = getnetbyname( str_addr ) ;
  210.     if ( nep == NULL || nep->n_addrtype != AF_INET || nep->n_net == 0 )
  211.         return( CANT_PARSE ) ;
  212.  
  213.     for ( i = 0, net_num = (unsigned long) nep->n_net ;; i++ )
  214.     {
  215.         if ( net_to_mask[ i ].mask == 0 )
  216.         {
  217.             msg( LOG_CRIT, func,
  218.                 "INTERNAL ERROR: Cannot process net number %ld", net_num ) ;
  219.             return( ERROR ) ;
  220.         }
  221.         if ( net_to_mask[i].lim < net_num && net_num <= net_to_mask[i+1].lim )
  222.         {
  223.             ca.addr_type = NET_ADDR ;
  224.             ca.addr = net_num << net_to_mask[ i ].shift ;
  225.             ca.mask = net_to_mask[ i ].mask ;
  226.             return( ( (*op)( addr_list, &ca ) == OK ) ? PARSED : ERROR ) ;
  227.         }
  228.     }
  229. }
  230.  
  231.  
  232.  
  233. PRIVATE result_e numeric_addr( str_addr, op, addr_list )
  234.     char *str_addr ;
  235.     status_e (*op)() ;
  236.     pset_h addr_list ;
  237. {
  238.     register unsigned long addr ;
  239.     register unsigned long mask ;
  240.     struct comp_addr ca ;
  241.  
  242.     addr = inet_addr( str_addr ) ;
  243.     if ( addr == -1 )
  244.         return( CANT_PARSE ) ;
  245.  
  246.     if ( addr == 0 )
  247.         mask = 0 ;            /* i.e. matches everything */
  248.     else
  249.     {
  250.         for ( mask = 0xFF ;; )
  251.         {
  252.             if ( addr & mask )
  253.                 break ;
  254.             mask <<= 8 ;
  255.             mask |= 0xFF ;
  256.         }
  257.         mask = ~( mask >> 8 ) ;
  258.     }
  259.     ca.mask = mask ;
  260.     ca.addr = addr ;
  261.     ca.addr_type = NUMERIC_ADDR ;
  262.     return( ( (*op)( addr_list, &ca ) == OK ) ? PARSED : ERROR ) ;
  263. }
  264.  
  265.  
  266.  
  267. PRIVATE result_e host_addr( str_addr, op, addr_list )
  268.     char *str_addr ;
  269.     status_e (*op)() ;
  270.     pset_h addr_list ;
  271. {
  272.     struct hostent *hep ;
  273.     struct comp_addr ca ;
  274.     char **ap ;
  275.  
  276.     hep = gethostbyname( str_addr ) ;
  277.     if ( hep == NULL || hep->h_addrtype != AF_INET )
  278.         return( CANT_PARSE ) ;
  279.  
  280.     ca.addr_type = HOST_ADDR ;
  281.     for ( ap = hep->h_addr_list ; *ap ; ap++ )
  282.     {
  283.         struct in_addr *iap = (struct in_addr *) (*ap) ;
  284.  
  285.         ca.addr = ntohl( iap->s_addr ) ;
  286.         ca.mask = 0xFFFFFFFF ;
  287.         if ( (*op)( addr_list, &ca ) == FAILED )
  288.             return( ERROR ) ;
  289.     }
  290.     return( PARSED ) ;
  291. }
  292.  
  293.  
  294. /*
  295.  * It is unclear whether this function should exist. It is really doing
  296.  * the job of a preprocessor.
  297.  */
  298. PRIVATE result_e factorized_addr( str_addr, op, addr_list )
  299.     char *str_addr ;
  300.     status_e (*op)() ;
  301.     pset_h addr_list ;
  302. {
  303.     char *p ;
  304.     char *fact_start ;
  305.     int pass ;
  306.     char last = DOT ;
  307.     unsigned num = 0 ;
  308.     int shift = 24 ;                        /* because we assume a 32-bit IP address */
  309.     register unsigned long addr = 0 ;
  310.     struct comp_addr ca ;
  311.     char *func = "factorized_addr" ;
  312.  
  313.     for ( p = str_addr ; *p != OPEN_CURLY_BRACKET ; last = *p++ )
  314.     {
  315.         if ( isdigit( *p ) )
  316.         {
  317.             num = num * 10 + *p - '0' ;
  318.             continue ;
  319.         }
  320.         switch ( *p )
  321.         {
  322.             case DOT:
  323.                 if ( last == DOT )
  324.                 {
  325.                     parsemsg( LOG_ERR, func,
  326.                         "Bad address: %s. Consecutive dots", str_addr ) ;
  327.                     return( ERROR ) ;
  328.                 }
  329.                 addr = addr * 256 + num ;
  330.                 num = 0 ;
  331.                 shift -= 8 ;
  332.                 break ;
  333.             
  334.             default:
  335.                 return( CANT_PARSE ) ;
  336.         }
  337.     }
  338.  
  339.     ca.addr_type = NUMERIC_ADDR ;
  340.     fact_start = p+1 ;
  341.     if ( addr != 0 )
  342.         addr <<= ( shift+8 ) ;
  343.  
  344.     /*
  345.      * First pass is for syntax checking
  346.      */
  347.     for ( pass = 0 ; pass < 2 ; pass++ )
  348.     {
  349.         num = 0 ;
  350.         for ( p = fact_start, last = COMMA ;; last = *p++ )
  351.         {
  352.             if ( isdigit( *p ) )
  353.             {
  354.                 num = num * 10 + *p - '0' ;
  355.                 continue ;
  356.             }
  357.             switch ( *p )
  358.             {
  359.                 case COMMA:
  360.                 case CLOSED_CURLY_BRACKET:
  361.                     if ( last == COMMA )
  362.                     {
  363.                         parsemsg( LOG_ERR, func,
  364.                             "Bad address: %s. Consecutive commas", str_addr ) ;
  365.                         return( ERROR ) ;
  366.                     }
  367.  
  368.                     if ( pass == 1 )
  369.                     {
  370.                         ca.addr = addr + ( num << shift ) ;
  371.                         ca.mask = ~( ( 1 << shift ) - 1 ) ;
  372.                         if ( (*op)( addr_list, &ca ) == FAILED )
  373.                             return( ERROR ) ;
  374.                         num = 0 ;
  375.                     }
  376.                     break ;
  377.                 
  378.                 default:
  379.                     parsemsg( LOG_ERR, func, "Bad address: %s", str_addr ) ;
  380.                     return( ERROR ) ;
  381.             }
  382.             if ( *p == CLOSED_CURLY_BRACKET )
  383.             {
  384.                 if ( p[1] != NUL )
  385.                 {
  386.                     parsemsg( LOG_ERR, func, "Bad address: %s", str_addr ) ;
  387.                     return( ERROR ) ;
  388.                 }
  389.  
  390.                 if ( pass == 0 )
  391.                     break ;
  392.                 else
  393.                     return( PARSED ) ;
  394.             }
  395.         }
  396.     }
  397.     /* NOTREACHED */
  398. }
  399.  
  400.  
  401. PRIVATE status_e addrlist_op( addr_list, op, str_addr )
  402.     pset_h addr_list ;
  403.     status_e (*op)() ;
  404.     char *str_addr ;
  405. {
  406.     int i ;
  407.     static result_e (*addr_parser[])() =
  408.         {
  409.             numeric_addr,
  410.             factorized_addr,
  411.             net_addr,
  412.             host_addr,
  413.             NULL
  414.         } ;
  415.     char *func = "addrlist_op" ;
  416.  
  417.     for ( i = 0 ; addr_parser[ i ] != NULL ; i++ )
  418.         switch ( (*addr_parser[ i ])( str_addr, op, addr_list ) )
  419.         {
  420.             case PARSED:
  421.                 return( OK ) ;
  422.             
  423.             case ERROR:
  424.                 return( FAILED ) ;
  425.         }
  426.  
  427.     parsemsg( LOG_ERR, func,
  428.             "not a numeric address, net name or host name: %s", str_addr ) ;
  429.     return( OK ) ;
  430. }
  431.  
  432.  
  433. status_e addrlist_add( addr_list, str_addr ) 
  434.     pset_h addr_list ;
  435.     char *str_addr ;
  436. {
  437.     return( addrlist_op( addr_list, add, str_addr ) ) ;
  438. }
  439.  
  440.  
  441. status_e addrlist_remove( addr_list, str_addr ) 
  442.     pset_h addr_list ;
  443.     char *str_addr ;
  444. {
  445.     return( addrlist_op( addr_list, remove, str_addr ) ) ;
  446. }
  447.  
  448.  
  449. status_e addrlist_copy( from, to )
  450.     pset_h from ;
  451.     pset_h *to ;
  452. {
  453.     status_e copy_pset() ;
  454.  
  455.     return( copy_pset( from, to, comp_addr_allocator ) ) ;
  456. }
  457.  
  458.